package com.example.teesystem.service.impl;

import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.teesystem.common.cache.CourseCache;
import com.example.teesystem.common.cache.UserCache;
import com.example.teesystem.common.exception.CustomException;
import com.example.teesystem.common.utils.FileUtil;
import com.example.teesystem.common.utils.ResultCode;
import com.example.teesystem.entity.*;
import com.example.teesystem.entity.Class;
import com.example.teesystem.entity.vo.PageResponseVo;
import com.example.teesystem.entity.vo.assistant.AssistantResponseVo;
import com.example.teesystem.entity.vo.course.CourseResponseVo;
import com.example.teesystem.entity.vo.course.CourseSelectVo;
import com.example.teesystem.entity.vo.course.CourseUpdateVo;
import com.example.teesystem.entity.vo.course.CourseUploadVo;
import com.example.teesystem.filter.MyHandlerInterceptor;
import com.example.teesystem.mapper.AssistantMapper;
import com.example.teesystem.mapper.ClassMapper;
import com.example.teesystem.mapper.ClassStudentMapper;
import com.example.teesystem.mapper.CourseMapper;
import com.example.teesystem.service.CourseService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
* @author 28131
* @description 针对表【t_course】的数据库操作Service实现
* @createDate 2022-03-23 12:41:48
*/
@Service
@RequiredArgsConstructor
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
    implements CourseService{
    private final ClassStudentMapper classStudentMapper;
    private final ClassMapper classMapper;
    private final AssistantMapper assistantMapper;
    private final CourseMapper courseMapper;
    
    @Override
    public PageResponseVo<CourseResponseVo> getCourses(Integer cur, Integer size) {
        Page<Course> coursePage = new Page<>(cur, size);
        Page<Course> result = this.page(coursePage);
        return new PageResponseVo<>(this.convertToResponseVos(result.getRecords()), result.getCurrent(), result.getSize(), result.getPages());
    }
    
    @Override
    public PageResponseVo<CourseResponseVo> getCourseByConditions(CourseSelectVo courseSelectVo) {
        String name = courseSelectVo.getName();
        String teacher = courseSelectVo.getTeacherName() != null ? courseSelectVo.getTeacherName() : "";
        
        // 从姓名中检索 id 列表
        List<Integer> ids = UserCache.userMap.entrySet().stream()
                .filter(entry -> entry.getValue().getMyName().contains(teacher))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        
        // 查询数据库获取数据
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        wrapper.like(Validator.isNotEmpty(name), "name", name)
                .in(!ids.isEmpty(), "teacher", ids);
        Page<Course> coursePage = new Page<>(courseSelectVo.getCur(), courseSelectVo.getSize());
        Page<Course> result = this.page(coursePage, wrapper);
        
        return new PageResponseVo<>(this.convertToResponseVos(result.getRecords()), result.getCurrent(), result.getSize(), result.getPages());
    }
    
    @Override
    public boolean addCourse(CourseUploadVo courseUploadVo) {
        Course course = new Course();
        BeanUtils.copyProperties(courseUploadVo, course);
        if(this.save(course)){
            CourseCache.courseMap.put(course.getId(), this.getById(course.getId()));
            return true;
        }
        return false;
    }
    
    @Override
    public boolean updateCourse(CourseUpdateVo courseUpdateVo) {
        Course course = new Course();
        BeanUtils.copyProperties(courseUpdateVo, course);
        if(this.updateById(course)) {
            CourseCache.courseMap.put(course.getId(), this.getById(course.getId()));
            return true;
        }
        return false;
    }
    
    @Override
    public List<CourseResponseVo> getCourseByUid(int uid) {
        List<Course> courses = CourseCache.courseMap.values().stream()
                .filter(course -> course.getTeacher() == uid)
                .collect(Collectors.toList());
        return this.convertToResponseVos(courses);
    }
    
    @Override
    public CourseResponseVo getCourseById(Integer id) {
        return this.convertToResponseVo(CourseCache.courseMap.get(id));
    }
    
    @Override
    public List<CourseResponseVo> getCourseByAssistantId(Integer assistantId){
        QueryWrapper<Assistant> wrapper = new QueryWrapper<>();
        wrapper.eq("assistant_id", assistantId);
        List<Course> courseList = this.assistantMapper.selectList(wrapper).stream()
                .map(assistant -> CourseCache.courseMap.get(assistant.getCourseId()))
                .collect(Collectors.toList());
        return this.convertToResponseVos(courseList);
    }


    @Override
    public boolean delete(Integer id) {
        if(this.removeById(id)) {
            CourseCache.courseMap.remove(id);
            return true;
        }
        return false;
    }
    
    @Override
    public List<CourseResponseVo> getCourseByStudentId(Integer studentId) {
        QueryWrapper<ClassStudent> classStudentQueryWrapper = new QueryWrapper<>();
        classStudentQueryWrapper.eq("student_id", studentId);
        List<Integer> classIds = this.classStudentMapper.selectList(classStudentQueryWrapper).stream()
                .map(ClassStudent::getClassId)
                .collect(Collectors.toList());
        if(classIds.isEmpty()) {
            throw new CustomException(ResultCode.LOG_NOT_EXIST);
        }
    
        return this.classMapper.selectBatchIds(classIds).stream()
                .map(Class::getCourseId)
                .map(this::getCourseById)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<AssistantResponseVo> getAssistants(Integer id) {
        return this.assistantMapper.selectAllByCourseId(id)
                .stream()
                .map(assistant -> {
                    AssistantResponseVo responseVo = new AssistantResponseVo();
                    BeanUtils.copyProperties(assistant, responseVo);
                    User user = UserCache.userMap.get(assistant.getUploadId());
                    responseVo.setUploadName(user != null ? user.getMyName() : "");
                    return responseVo;
                })
                .collect(Collectors.toList());
    }

    @Override
    public boolean updateDataImg(Integer courseId, String dataUrl) {
        try{
            courseMapper.updateDataImgById(courseId,dataUrl);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    private List<CourseResponseVo> convertToResponseVos(List<Course> courses) {
        return courses.stream()
                .map(this::convertToResponseVo)
                .collect(Collectors.toList());
    }
    
    private CourseResponseVo convertToResponseVo(Course course) {
        CourseResponseVo courseResponseVo = new CourseResponseVo();
        BeanUtils.copyProperties(course, courseResponseVo);
        
        String myName = UserCache.userMap.getOrDefault(course.getTeacher(), UserCache.NONE_USER).getMyName();
        String uploadName = UserCache.userMap.getOrDefault(course.getUploadId(), UserCache.NONE_USER).getMyName();
        
        courseResponseVo.setTeacher(myName != null ? myName : "用户不存在");
        courseResponseVo.setUploadName(uploadName != null ? uploadName : "用户不存在");

        if(course.getImgUrl()!=null && !course.getImgUrl().equals("")) {
            courseResponseVo.setImgUrl(FileUtil.FILE_PREFIX+course.getImgUrl());
        }
        if(course.getDataImg()!=null && !course.getDataImg().equals("")){
            String[] datas = course.getDataImg().trim().split("\\$");
            for(int i = 0; i < datas.length; i++){
                datas[i] = FileUtil.FILE_PREFIX+datas[i];
            }
            courseResponseVo.setDataImg(datas);
        }
        return courseResponseVo;
    }
}
